/*************************************************************************
	> File Name: 001.AC.cpp
	> Author: Maureen 
	> Mail: Maureen@qq.com 
	> Created Time: 三  2/24 17:03:16 2021
 ************************************************************************/

#include <iostream>
using namespace std;

#define BASE 26

typedef struct Node {
    int flag;
    const char *str;
    struct Node *next[BASE];
    struct Node *fail; //等价匹配关系指针
} Node;
int cnt = 0; //字典树中节点个数

Node *getNewNode() {
    cnt += 1;
    Node *p = (Node *)malloc(sizeof(Node));
    p->flag = 0;
    memset(p->next, 0, sizeof(p->next));
    p->fail = NULL;
    return p;
}

//建立字典树
void insert(Node *root, const char *str) {
    for (int i = 0; str[i]; i++) {
        int ind = str[i] - 'a';
        if (root->next[ind] == NULL) root->next[ind] = getNewNode();
        root = root->next[ind];
    }
    root->flag = 1;
    root->str = strdup(str); //叶子节点保存字符串副本
    return ;
}

//建立AC自动机：增加等价匹配关系指针
void build_ac(Node *root) {
    //层序遍历,申请队列空间
    Node **q = (Node **)malloc(sizeof(Node *) * (cnt + 5));
    int head = 0, tail = 0;
    root->fail = NULL;
    for (int i = 0; i < BASE; i++) {
        if (root->next[i] == NULL) continue;
        //每个节点的等价匹配指针都是根节点
        root->next[i]->fail = root;
        //放进队列中
        q[tail++] = root->next[i];
    }
    
    while (head < tail) {
        Node *p = q[head++];
        for (int i = 0; i < BASE; i++) {
            Node *c = p->next[i];
            Node *k = p->fail;
            if (c == NULL) continue;
            while (k && k->next[i] == NULL) k = k->fail;
            if (k == NULL) k = root;
            if (k->next[i]) k = k->next[i];
            //根据父节点找到子节点的等价匹配指针
            c->fail = k;
            q[tail++] = c;
        }
    }
    free(q);
    return ;
}

void match(Node *root, const char *text) {
    Node *p = root, *q;
    for (int i = 0; text[i]; i++) {
        printf("input : %c\n", text[i]);
        int ind = text[i] - 'a';
        while (p && p->next[ind] == NULL) p = p->fail;
        if (p == NULL) p = root;
        if (p->next[ind]) p = p->next[ind];
        //之所以要使用q，是因为当前节点可能不是匹配到的单词，但是它的fail指针指向的节点可能是
        q = p;
        while (q) {
            if (q->flag == 1) printf("find: %s\n", q->str);
            q = q->fail;
        }
    }
    return ;
}

void clear(Node *root) {
    if (root == NULL) return ;
    for (int i = 0; i < BASE; i++) {
        clear(root->next[i]);
    }
    free(root);
    return ;
}

int main() {
    int n;
    scanf("%d", &n);
    char str[100];
    Node *root = getNewNode();
    for (int i = 0; i < n; i++) {
        scanf("%s", str);
        insert(root, str);
    }
    build_ac(root);
    scanf("%s", str);
    match(root, str);

    return 0;
}
